<template>
	<view>
		<camera flash="off" device-position="front" resolution="high" @stop="stopCamera" @error="errorCamera"
			class="cameraBox">
			<cover-view class="cover">
				<cover-view class="camera">
					<cover-image class="cameraImg"
						src="https://fire-system.oss-cn-beijing.aliyuncs.com/web/fire-technology/faceBox.png"></cover-image>
				</cover-view>
				<cover-view class="cover-bottom cover-item">
					<cover-view class="detectInfo">{{ tipsText}}</cover-view>
				</cover-view>
			</cover-view>
		</camera>
		<canvas id="myCanvas" canvas-id="myCanvas"
			:style="'width:'+screenWidth+'px;'+'height:'+screenHeight+'px'"></canvas>
	</view>
</template>
<script>
	export default {
		data() {
			return {
				bgColor: '#fff', // 颜色
				tipsText: '请将脸部移入框内', // 错误文案提示
				tempImg: '', // 本地图片路径
				cameraEngine: null, // 相机引擎
				isAuthCamera: false, // 是否拥有相机权限
				setIntColor: null, // 颜色随机定时器
				actionsList: null, // 人脸检测数据
				isSuccess: false, //是否检测完成
				isFlag2: true,
				screenWidth: 375,
				screenHeight: 640,
				isVerify: false,
				translateY: -24,
				timer: null,
				isFlag: true,
				origin: null,
				base64: "",
				personId: "",
				faceInfo: {
					maintenanceId: '',
					faceState: '', // 维保状态（1开始，2暂停，3结束）
					imageBase64: '', // 图片base64
					latitude: '', // 纬度
					longitude: '', // 经度
					accessToken: '', // 百度accesstoken
					sessionCode: '', // 用户需要大声读出数字
					videoPath: '', // 上传视频后返回的临时视频路径
					videoBase64: '', // 视频base64
				},
				paramsList: {}
			};
		},
		onLoad(e) {
			console.log('前边传过来的数据', e)
			this.getCameraPurview(); // 初始化相机--检测是否授权
			this.paramsList = JSON.parse(e.paramsList)
		},
		methods: {
			// 获取相机权限---检测是否获取权限
			getCameraPurview() {
				uni.getSetting({
					success: (res) => {
						if (res.authSetting['scope.camera'] === true) {
							this.onpenCameraFrame() // 打开相机，开始人脸检测
						} else if (res.authSetting['scope.camera'] === false) {
							this.getCameraAuth() // 获取相机权限---进行授权
						} else {
							this.onpenCameraFrame() // 打开相机，开始人脸检测
						}
					}
				})
			},
			// 获取相机权限---进行授权
			getCameraAuth() {
				uni.showModal({
					title: '温馨提示',
					content: '需要获取您摄像头权限才能更好的为您服务！是否授权摄像头权限？',
					confirmText: '授权',
					confirmColor: '#f94218',
					success: (res) => {
						if (res.confirm) {
							// 选择弹框内授权
							uni.openSetting({
								success: (res) => {
									if (res.authSetting['scope.camera']) {
										this.onpenCameraFrame() // 打开相机，开始人脸检测
									} else {
										this.tipsText = "您未授权摄像头权限"
										this.cameraError() // 获取相机失败或者人脸核验失败
									}
								}
							})
						} else if (res.cancel) {
							this.tipsText = "您未授权摄像头权限"
							this.cameraError() // 获取相机失败或者人脸核验失败
						}
					}
				})
			},
			// 初始化相机引擎，开始人脸检测
			onpenCameraFrame() {
				// #ifdef MP-WEIXIN
				// 1、初始化人脸识别
				wx.initFaceDetect();
				// 2、创建 camera 上下文 CameraContext 对象
				this.cameraEngine = uni.createCameraContext();
				this.isShow = true;
				// 3、获取 Camera 实时帧数据
				const listener = this.cameraEngine.onCameraFrame((frame) => {
					if (this.isVerify) return
					console.log('实时帧', frame)
					// 动态设置canvas的宽高,不设置会导致部分机型人脸不完整导致不能识别-----很重要!很重要!很重要!
					if (this.isFlag2) {
						this.isFlag2 = false;
						this.screenWidth = frame.width;
						this.screenHeight = frame.height;
					}
					// 4、人脸识别，使用前需要通过 wx.initFaceDetect 进行一次初始化，推荐使用相机接口返回的帧数据
					setTimeout(() => {
						wx.faceDetect({
							frameBuffer: frame.data,
							width: frame.width,
							height: frame.height,
							enablePoint: true,
							enableConf: true,
							enableAngle: true,
							enableMultiFace: true,
							success: async (faceData) => {
								let face = faceData.faceInfo[0]
								if (face.x == -1 || face.y == -1) {
									this.tipsText = '检测不到人'
								}
								if (faceData.faceInfo.length > 1) {
									this.tipsText = '请保证只有一个人'
								} else {
									const {
										pitch,
										roll,
										yaw
									} = face.angleArray;
									const standard = 0.5
									if (Math.abs(pitch) >= standard || Math.abs(roll) >=
										standard ||
										Math.abs(yaw) >= standard) {
										this.tipsText = '请平视摄像头'
									} else if (face.confArray.global <= 0.8 || face.confArray
										.leftEye <=
										0.8 || face.confArray.mouth <= 0.8 || face.confArray
										.nose <= 0.8 ||
										face.confArray.rightEye <= 0.8) {
										this.tipsText = '请勿遮挡五官'
									} else {
										if (this.isVerify) return
										//人脸位置校验
										let centerWidth = 250;
										let centerHeight = 250;
										if (face.x > (frame.width - centerWidth) / 2 && face
											.x < (frame
												.width - centerWidth) / 2 + centerWidth && face
											.y > (frame
												.height - centerHeight) / 2 && face.y < (frame
												.height -
												centerHeight) / 2 + centerHeight) {
											this.tipsText = '人脸检测中...'
											uni.showLoading({
												title: '加载中'
											});
											this.isVerify = true;
											// 太快获取的人脸可能比较抽象,给用户一个准备时间
											let that = this
											setTimeout(async () => {
												this.faceInfo.imageBase64 =
													await that
													.changeDataToBase64(
														frame);
												uni.setStorageSync(
													'imageBase64', this
													.faceInfo.imageBase64);
												that.$pageJump.reLaunch(
													'/pages/maintenance/mechanism/home/components/mechanismWork/mechanismWorking?paramsList=' +
													JSON.stringify(that
														.paramsList)
												)
											}, 1300)
										} else {
											this.tipsText = '请将人脸对准中心位置'
										}

									}
								}
							},
							fail: (err) => {
								if (this.isVerify) return
								if (err.x == -1 || err.y == -1) {
									this.tipsText = '检测不到人'
								} else {
									this.tipsText = err.errMsg || '网络错误，请退出页面重试'
								}
							},
						})
					}, 1500)

				})
				// 5、开始监听帧数据
				listener.start()
				// #endif
			},
			// android or ios获取视频帧
			changeDataToBase64(frame) {
				return new Promise((resolve, reject) => {
					let data = new Uint8Array(frame.data);
					let clamped = new Uint8ClampedArray(data);
					let width = this.screenWidth;
					let height = frame.height * this.screenWidth / frame.width;
					uni.canvasPutImageData({
						canvasId: 'myCanvas',
						x: 0,
						y: 0,
						width: frame.width,
						height: frame.height,
						data: clamped,
						success() { // 转换临时文件
							uni.canvasToTempFilePath({
								x: 0,
								y: 0,
								width: width,
								height: height,
								canvasId: 'myCanvas',
								fileType: 'jpg',
								destWidth: width,
								destHeight: height, // 精度修改  
								quality: 0.5,
								success(res) {
									// 临时文件转base64
									uni.getFileSystemManager().readFile({
										filePath: res.tempFilePath, //选择图片返回的相对路径 
										encoding: 'base64', //编码格式  
										success: res => {
											console.log(res.data)
											uni.hideLoading();
											// 保存base64
											resolve(res.data);
										}
									})
								},
								fail(res) {
									reject(false);
								}
							});
						},
						fail(error) {
							console.log(error);
						}
					})
				})
			},
			// 获取视频帧------ios
			handleVideoImg() {
				this.isReuqest = true
				var tf = this.temframe;
				var that = this;
				uni.canvasPutImageData({
					canvasId: 'tempCanvas',
					x: 0,
					y: 0,
					width: tf.width,
					height: tf.height,
					data: tf.data,
					success: function(res) {
						console.log('绘制成功', res)
						uni.canvasToTempFilePath({
							x: 0,
							y: 0,
							width: tf.width,
							height: tf.height,
							canvasId: 'tempCanvas',
							fileType: 'png',
							destWidth: tf.width,
							destHeight: tf.height,
							quality: 1, // 精度修改
							success(res) {
								console.log('图片地址', res.tempFilePath)
								that.imgSrc = res.tempFilePath
								let mybase64 = wx.getFileSystemManager().readFileSync(res.tempFilePath,
									'base64');
								console.log('图片', mybase64)
							},
							fail(e) {
								console.log('人脸识别失败', e);
								setTimeout(() => {
									that._takePhoto();
								}, 500);
							}
						});

					},
					fail(e) {
						console.log('人脸识别失败', e);
						setTimeout(() => {
							that._takePhoto();
						}, 500);
					}
				});

			},
			// 拍照-------安卓
			handleTakePhotoClick() {
				this.tipsText = '人脸识别中···';
				this.cameraEngine.takePhoto({
					quality: 'high',
					success: ({
						tempImagePath
					}) => {
						let mybase64 = wx.getFileSystemManager().readFileSync(tempImagePath, 'base64');
						console.log('图片', mybase64)
						this.imgSrc = mybase64
					}
				});
			},
			// 切换颜色
			changeColor() {
				let colorList = ['red', 'blue', 'yellow'];
				let colorIndex = 0;
				this.setIntColor = setInterval(() => {
					colorIndex = (colorIndex + 1) % colorList.length;
					this.bgColor = colorList[colorIndex]
					console.log('this.bgColor', this.bgColor);
				}, 1000); // 每1000毫秒（1秒）改变一次颜色
			},
			// 关闭相机
			hideModal() {
				uni.stopFaceDetect()
				this.tipsText = '检测不到人脸'
			},
			// 相机发生错误
			errorCamera() {
				this.tipsText = '相机异常'
				this.cameraError() // 人脸核验失败
			},
			// 相机停止
			stopCamera() {
				this.tipsText = '相机异常'
				this.cameraError() // 人脸核验失败
			},
			// 人脸核验失败
			cameraError() {
				let that = this
				that.t = setTimeout(() => {
					that.$pageJump.reLaunch(
						'/pages/maintenance/mechanism/home/components/mechanismWork/mechanismWorking?maintenanceId=' +
						that.paramsList.maintenanceId
					)
					clearTimeout(that.t)
				}, 1000);
			},
		}

	}
</script>

<style scoped lang="scss">
	.detectInfo {
		padding: 20rpx 0rpx;
		font-size: 40rpx;
		text-align: center;
		animation-duration: 1.5s;
		color: #0081ff;
		z-index: 999;
	}

	.cameraBox {
		width: 100vw;
		height: 100vh;
		position: fixed;
		top: 0;
		left: 0;
	}

	.cover {
		width: 100vw;
		height: 100vh;
		display: flex;
		flex-direction: column;
	}

	.cover-bottom {
		width: 100%;
		position: absolute;
		left: 0;
		bottom: 25%;
		z-index: 99999;
	}

	.camera {
		width: 100vw;
		height: 100vh;
		/* transform: scale(1.05); */
		z-index: 999;

		.cameraImg {
			width: 100%;
			height: 100%;
		}
	}

	#myCanvas {
		position: absolute;
		z-index: 1;
		top: -10000px;
	}
</style>